package com.easy.generator;


import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

public class ControllerGenerator {

    public static void generate() throws Exception {
        // 获取类加载器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        // 扫描包下的所有类
        Set<Class<?>> classes = scanClasses(Easy.BEAN_PACKAGE, classLoader);
        // 为每个实体类生成Controller
        for (Class<?> clazz : classes) {
            if (isEntityClass(clazz)) {
                generateControllerFile(clazz);
            }
        }
    }

    private static Set<Class<?>> scanClasses(String packageName, ClassLoader classLoader) throws Exception {
        Set<Class<?>> classes = new HashSet<>();
        String path = packageName.replace('.', '/');
        Enumeration<URL> resources = classLoader.getResources(path);

        while (resources.hasMoreElements()) {
            URL resource = resources.nextElement();
            if (resource.getProtocol().equals("file")) {
                classes.addAll(findClasses(new File(resource.getFile()), packageName));
            }
        }
        return classes;
    }

    private static Set<Class<?>> findClasses(File directory, String packageName) throws ClassNotFoundException {
        Set<Class<?>> classes = new HashSet<>();
        if (!directory.exists()) return classes;

        File[] files = directory.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                classes.addAll(findClasses(file, packageName + "." + file.getName()));
            } else if (file.getName().endsWith(".class")) {
                String className = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
                classes.add(Class.forName(className));
            }
        }
        return classes;
    }

    private static boolean isEntityClass(Class<?> clazz) {
        // 简单的实体类判断逻辑，可根据实际需求扩展
        return !clazz.isInterface() && !Modifier.isAbstract(clazz.getModifiers());
    }

    private static void generateControllerFile(Class<?> entityClass) throws IOException {
        String className = entityClass.getSimpleName();
        String controllerName = className + "Controller";
        String serviceName = className + "Service";
        String classLowerName=String.valueOf(className.charAt(0)).toLowerCase() + className.substring(1);
        String serviceVarName = classLowerName + "Service";

        File dir = new File(Easy.PROJECT_ABSOLUTE_URL + "/src/main/java/" + Easy.CONTROLLER_PACKAGE.replace('.', '/'));
        if (!dir.exists()) {
            dir.mkdirs();
        }

        File file = new File(dir, controllerName + ".java");
        try (PrintWriter out = new PrintWriter(file)) {
            String classText="package "+Easy.CONTROLLER_PACKAGE+";\n" +
                    "\n" +
                    "import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;\n" +
                    "import com.baomidou.mybatisplus.extension.plugins.pagination.Page;\n" +
                    "\n" +
                    "import org.springframework.web.bind.annotation.*;\n" +
                    "import org.springframework.beans.factory.annotation.*;\n" +
                    "\n" +
                    "import "+Easy.BEAN_PACKAGE+".*;\n" +
                    "import "+Easy.SERVICE_PACKAGE+".*;\n" +
                    "import "+Easy.UTIL_PACKAGE+".*;\n" +
                    "\n" +
                    "@RestController\n" +
                    "@RequestMapping(\"/"+classLowerName+"\")\n" +
                    "@CrossOrigin\n"+
                    "public class "+controllerName+" {\n"+
                    "\n"+
                    "    @Autowired\n" +
                    "    private "+serviceName+" "+serviceVarName+";\n"+
                    "\n";
            out.println(classText);
            // 生成CRUD方法
            generateCrudMethods(out, className, serviceVarName);
            out.println("}");
        }
    }

    private static void generateCrudMethods(PrintWriter out, String className, String serviceVarName) {
        String varName = String.valueOf(className.charAt(0)).toLowerCase() + className.substring(1);
        String METHOD_TEMPLATE =
                "\n" +
                        "    @GetMapping\n" +
                        "    public Result getAll() {\n" +
                        "        return Result.success("+serviceVarName+".list());\n" +
                        "    }\n" +
                        "\n" +
                        "    @GetMapping(\"page\")\n" +
                        "    public Result getPage(Page page, @RequestParam(name = \"searchtext\", required = false) String searchtext) {\n" +
                        "        QueryWrapper wrapper =null;\n" +
                        "        if (searchtext != null && !searchtext.isEmpty()) {\n" +
                        "            wrapper = new QueryWrapper<>();\n" +
                        "            wrapper.like(\"name\", searchtext);\n" +
                        "        }\n" +
                        "        return Result.success("+serviceVarName+".page(page, wrapper));\n" +
                        "    }" +
                        "\n" +
                        "    @GetMapping(\"/{id}\")\n" +
                        "    public Result getById(@PathVariable(\"id\") Long id) {\n" +
                        "        return Result.success("+serviceVarName+".getById(id));\n" +
                        "    }\n" +
                        "\n" +
                        "    @PostMapping\n" +
                        "    public Result create(@RequestBody "+className+" entity) {\n" +
                        "        return Result.success("+serviceVarName+".save(entity));\n" +
                        "    }\n" +
                        "\n" +
                        "    @PutMapping\n" +
                        "    public Result update( @RequestBody "+className+" entity) {\n" +
                        "        return Result.success("+serviceVarName+".save(entity));\n" +
                        "    }\n" +
                        "\n" +
                        "    @DeleteMapping(\"/{id}\")\n" +
                        "    public Result delete(@PathVariable(\"id\") Long id) {\n" +
                        "        return Result.success("+serviceVarName+".removeById(id));\n" +
                        "    }";
        out.println(METHOD_TEMPLATE);
    }
}
